package com.reeygu.base;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CopyOnWriteArraySet;

/**
 * 研究数组的线程安全问题
 */
public class secure {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.print("Please enter the execution number:");
        int select = scanner.nextInt();
        switch (select) {
            case 1: ArrayListSecure(); break;
            case 2: VectorSecure(); break;
            case 3: CollectionSecure(); break;
            case 4: CopyOnWriteArrayListSecure(); break;
            case 5: CopyOnWriteSetSecure(); break;
            case 6: CopyOnWriteMapSecure(); break;
            default:
                System.out.println("error!");
        }
    }

    /**
     * ArrayList 是线程不安全的
     */
    public static void ArrayListSecure() {
        List<String> list = new ArrayList<>();
        for (int i = 0; i < 30; i++) {
            new Thread( () -> {
                list.add(UUID.randomUUID().toString().substring(1, 8));
                System.out.println(list);
            }, String.valueOf(i)).start();
        }
    }

    /**
     * 第一种解决方案： 使用Vector
     * Vector 是线程安全的， 但是效率太低了，是 jdk1.0 的对象
     */
    public static void VectorSecure() {
        List<String> list = new Vector<>();
        for (int i = 0; i < 30; i++) {
            new Thread( () -> {
                list.add(UUID.randomUUID().toString().substring(1, 8));
                System.out.println(list);
            }, String.valueOf(i)).start();
        }
    }

    /**
     * 第二种解决方案： 使用Collections.synchronizedList
     * Collections 是专门处理线程安全的一个工具类，也是比较古老的，专门处理线程安全的数组对象
     */
    public static void CollectionSecure() {
        List<String> list = Collections.synchronizedList(new ArrayList<>());
        for (int i = 0; i < 30; i++) {
            new Thread( () -> {
                list.add(UUID.randomUUID().toString().substring(1, 8));
                System.out.println(list);
            }, String.valueOf(i)).start();
        }
    }

    /**
     * 第二种解决方案： 使用 CopyOnWriteArrayList
     * CopyOnWriteArrayList 使用一种写时复制技术
     * 特点是并发读、独立写，只有在写操作时才会复制对象，写完后合并
     * 常用在读多写少的场景
     */
    public static void CopyOnWriteArrayListSecure() {
        List<String> list = new CopyOnWriteArrayList<>();
        for (int i = 0; i < 30; i++) {
            new Thread( () -> {
                list.add(UUID.randomUUID().toString().substring(1, 8));
                System.out.println(list);
            }, String.valueOf(i)).start();
        }
    }

    //set 和 map 与上一个方法一样，可以通过实现线程安全

    public static void CopyOnWriteSetSecure() {
        Set<String> list = new CopyOnWriteArraySet<>();
        for (int i = 0; i < 30; i++) {
            new Thread( () -> {
                list.add(UUID.randomUUID().toString().substring(1, 8));
                System.out.println(list);
            }, String.valueOf(i)).start();
        }
    }

    public static void CopyOnWriteMapSecure() {
        Map<String, String> map = new ConcurrentHashMap<>();
        for (int i = 0; i < 30; i++) {
            String key = String.valueOf(i);
            new Thread( () -> {
                map.put(key, UUID.randomUUID().toString().substring(1, 8));
                System.out.println(map);
            }, String.valueOf(i)).start();
        }
    }
}
